﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Xml;
using System.ComponentModel;
using SpeakupBackend.Classes;

namespace SpeakupBackend.Themes
{
    [Serializable]
    public sealed partial class WorkshopTheme: IXmlSerializable, 
                                IEquatable<WorkshopTheme>, 
                                IComparable, 
                                IComparable<WorkshopTheme>,
                                INotifyPropertyChanged,
                                ITheme
    {
        public WorkshopTheme(WorkshopClassType classType, LevelGroup levelGroup, Week week, String name)
        {
            this.m_classType = classType;
            this.m_levelGroup = levelGroup;
            this.m_week = week;
            this.m_name = name;
        }

        Week m_week;
        public Week Week
        {
            get
            {
                return m_week;
            }
        }

        LevelGroup m_levelGroup;
        public LevelGroup LevelGroup
        {
            get
            {
                return m_levelGroup;
            }
        }

        WorkshopClassType m_classType;
        public WorkshopClassType ClassType
        {
            get
            {
                return m_classType;
            }
        }

        String m_name;
        public String Name
        {
            get
            {
                return m_name;
            }
            set
            {
                if (m_name != value)
                {
                    m_name = value;
                    OnPropertyChanged("Name");
                }
            }
        }
        
        public override string ToString()
        {
            return String.Format("Week: {0,2} | Level: {1,5} | Class: {2,10} | {3}", 
                Week,
                LevelGroup,
                ClassType,
                Name);
        }

        public override bool Equals(object obj)
        {
            return Equals(obj as WorkshopTheme);
        }

        public bool Equals(WorkshopTheme other)
        {
            return ClassHelper.IEquatableEquals(this, other);
        }

        public override int GetHashCode()
        {
            return ClassHelper.GetHashCode(ClassType, LevelGroup, Week);
        }

        public int CompareTo(object obj)
        {
            return CompareTo((WorkshopTheme)obj);
        }

        public int CompareTo(WorkshopTheme other)
        {
            if (ClassType != other.ClassType)
            {
                return ClassType.CompareTo(other.ClassType);
            }
            else if (LevelGroup != other.LevelGroup)
            {
                return LevelGroup.CompareTo(other.LevelGroup);
            }
            
            return Week.CompareTo(other.Week);
        }

        #region Comparison operators

        static public bool operator ==(WorkshopTheme rhs, WorkshopTheme lhs)
        {
            return ClassHelper.OperatorEqual(rhs, lhs);
        }

        static public bool operator !=(WorkshopTheme rhs, WorkshopTheme lhs)
        {
            return ClassHelper.OperatorNotEqual(rhs, lhs);
        }

        static public bool operator >(WorkshopTheme rhs, WorkshopTheme lhs)
        {
            return rhs.CompareTo(lhs) > 0;
        }

        static public bool operator <(WorkshopTheme rhs, WorkshopTheme lhs)
        {
            return rhs.CompareTo(lhs) < 0;
        }

        static public bool operator >=(WorkshopTheme rhs, WorkshopTheme lhs)
        {
            return rhs.CompareTo(lhs) >= 0;
        }

        static public bool operator <=(WorkshopTheme rhs, WorkshopTheme lhs)
        {
            return rhs.CompareTo(lhs) <= 0;
        }

        #endregion
    }
    
    /// <summary>
    /// xml serialization/deserelization
    /// </summary>
    public sealed partial class WorkshopTheme
    {
        internal WorkshopTheme()
        {
            //for xml deserialization
        }

        private static readonly string WeekAttributeName = "week";
        private static readonly string LevelAttributeName  = "level";
        private static readonly string ClassTypeAttributeName  = "class";

        public XmlSchema GetSchema()
        {
            throw new NotImplementedException();
        }
        
        public void ReadXml(XmlReader reader)
        {
            string classValue = reader.GetAttribute(ClassTypeAttributeName);
            if (classValue == null)
            {
                throw new FormatException(String.Format("WorkshopTheme element: Required attribute \"{0}\" is missing.", ClassTypeAttributeName));
            }
            m_classType = WorkshopClassType.GetWorkshopClassType(classValue);

            string levelValue = reader.GetAttribute(LevelAttributeName);
            if (levelValue == null)
            {
                throw new FormatException(String.Format("WorkshopTheme element: Required attribute \"{0}\" is missing.", LevelAttributeName));
            }
            m_levelGroup = LevelGroup.DefaultFactory.GetLevelGroup(levelValue);

            string weekValue = reader.GetAttribute(WeekAttributeName);
            if (weekValue == null)
            {
                throw new FormatException(String.Format("WorkshopTheme element: Required attribute \"{0}\" is missing.", WeekAttributeName));
            }
            m_week = Week.GetWeek(weekValue);
            
            Name = reader.ReadString();

            reader.ReadEndElement();
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteAttributeString(ClassTypeAttributeName, ClassType.ToString());
            writer.WriteAttributeString(LevelAttributeName, LevelGroup.ToString());
            writer.WriteAttributeString(WeekAttributeName, Week.ToString());
            writer.WriteString(Name);
        }        
    }

    /// <summary>
    /// WorkshopTheme Attended property
    /// </summary>
    public sealed partial class WorkshopTheme: ThemeBase
    {
        public override bool IsCompatibleClass(Class cl)
        {
            if (cl.Level == null)
            {
                return false;
            }

            if (!WorkshopClassType.IsValidClassType(cl.Name.Type))
            {
                return false;
            }

            //Level, Week # and ClassType
            Level clLevel = cl.Level;
            Week clWeek = Week.GetWeek(cl.Time.Date);
            WorkshopClassType clType = WorkshopClassType.GetWorkshopClassType(cl.Name.Type);

            if (LevelGroup.ContainsLevel(clLevel) && Week == clWeek && ClassType == clType)
            {
                return true;
            }

            return false;
        }            
    }
}
